/*
 * $Id: utl_getsysinfo.c,v 1.3 2006-03-21 16:15:16 bacon Exp $
 */

#include <xp/sys/utl.h>

#if defined(_WIN32)
	#include <pdh.h>
#elif defined(__linux)
	#include <unistd.h>
	#include <sys/sysinfo.h>
#elif defined(__FreeBSD__)
	#include <sys/sysctl.h>
#elif defined(sun)||defined(__sun)
	#include <kstat.h>
#elif 
	#include <sys/sysctl.h>
#endif

int xp_getsysinfo (xp_sysinfo_t* sys)
{
#if defined(_WIN32)
	SYSTEM_INFO sys_info;
	GetSystemInfo (&sys_info);
	sys->ncpus = sys_info.dwNumberOfProcessors;
	sys->uptime = 0; /* TODO: get uptime */
	return 0;

#elif defined(__linux)
	struct sysinfo info;

	long v = sysconf (_SC_NPROCESSORS_CONF);
	if (v == -1) return -1;
	sys->ncpus = (xp_size_t)v;

	if (sysinfo(&info) == -1) return -1;
	sys->uptime = (xp_time_t)info.uptime * XP_MSEC_IN_SEC;

	return 0;

#elif defined(__FreeBSD__)
	int mib[2];
	xp_size_t len;
	struct timeval boottime;
	xp_time_t now;

	mib[0] = CTL_HW;
	mib[1] = HW_NCPU;
	len = xp_sizeof(sys->ncpus); 
	if (sysctl(mib, 2, &sys->ncpus, &len, XP_NULL, 0) == -1) return -1;

	mib[0] = CTL_KERN;
	mib[1] = KERN_BOOTTIME;
	len = xp_sizeof(boottime);

	if (xp_gettime(&now) == -1) return -1;
	if (sysctl(mib, 2, &boottime, &len, XP_NULL, 0) == -1) return -1;

	sys->uptime = now - ((xp_time_t)boottime.tv_sec * XP_MSEC_IN_SEC);
	return 0;

#elif defined(sun) || defined(__sun)
	kstat_ctl_t* kc;
	kstat_t* ks;
	kid_t kid;
	kstat_named_t* tmp;

	kc = kstat_open ();
	if (kc == XP_NULL) return -1;

	ks = kstat_lookup (kc, "unix", -1, "system_misc");
	if (ks == XP_NULL) 
	{
		kstat_close (kc);
		return -1;
	}

	kid = kstat_read (kc, ks, XP_NULL);
	if (kid == -1) 
	{
		kstat_close (kc);
		return -1;
	}

	tmp = kstat_data_lookup (ks, "ncpus");
	if (tmp == NULL) 
	{
		kstat_close (kc);
		return -1;
	}

	sys->ncpus = (xp_size_t)tmp->value.ul;

	ks = kstat_lookup (kc, "unix", -1, "system_misc");
	if (ks == XP_NULL) 
	{
		kstat_close (kc);
		return -1;
	}

	kid = kstat_read (kc, ks, XP_NULL);
	if (kid == -1) 
	{
		kstat_close (kc);
		return -1;
	}

	tmp = kstat_data_lookup (ks, "lbolt");
	if (tmp == XP_NULL) 
	{
		kstat_close (kc);
		return -1;
	}

	sys->uptime = (xp_time_t)tmp->value.ul * 10;

	kstat_close (kc);
	return 0;

#else
	return -1;

#endif

}

